﻿namespace MobileTrack.Web.Tests.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Principal;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    using System.Web.Security;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using MobileTrack.Core;
    using MobileTrack.Core.Data;
    using MobileTrack.Core.Model;
    using MobileTrack.Web.Controllers;
    using MobileTrack.Web.ViewModels;
    using Moq;

    [TestClass]
    public class SeguimientosControllerFixture
    {
        private IList<Celular> celulares;
        private IList<Venta> ventas;
        private string userRole;
        private bool isInRole;

        private Mock<IRepository<Celular>> celularesRepositoryMock;
        private Mock<IRepository<Venta>> ventasRepositoryMock;
        private Mock<IRepositories> repositoriesMock;
        private Mock<IPrincipal> principalMock;

        [TestInitialize]
        public void TestInitialize()
        {
            this.celulares = new List<Celular>();
            this.ventas = new List<Venta>();
            this.userRole = string.Empty;
            this.isInRole = false;

            this.celularesRepositoryMock = new Mock<IRepository<Celular>>();
            this.celularesRepositoryMock.Setup(cr => cr.All).Returns(() => this.celulares.AsQueryable());

            this.ventasRepositoryMock = new Mock<IRepository<Venta>>();
            this.ventasRepositoryMock.Setup(vr => vr.All).Returns(() => this.ventas.AsQueryable());

            this.repositoriesMock = new Mock<IRepositories>();
            this.repositoriesMock.Setup(rs => rs.Celulares).Returns(() => this.celularesRepositoryMock.Object);
            this.repositoriesMock.Setup(rs => rs.Ventas).Returns(() => this.ventasRepositoryMock.Object);

            this.principalMock = new Mock<IPrincipal>();
        }

        [TestMethod]
        public void IndexShouldRedirectToImeiViewOnNullImei()
        {
            this.userRole = Constants.AdministradorRole;
            this.isInRole = true;

            var controller = this.CreateSeguimientosController();

            var result = controller.Index((long?)null) as RedirectToRouteResult;
            Assert.IsNotNull(result);

            Assert.AreEqual(2, result.RouteValues.Count);
            Assert.AreEqual("index", ((string)result.RouteValues["action"]).ToLower());
            Assert.AreEqual("imeis", ((string)result.RouteValues["controller"]).ToLower());
        }

        [TestMethod]
        public void IndexShouldReturnLastSeguimientoOnValidImei()
        {
            this.userRole = Constants.AdministradorRole;
            this.isInRole = true;
            DateTime today = DateTime.Today;
            Celular cel = new Celular { Imei = 123456789123456 };
            cel.Seguimientos.Add(new Seguimiento { Id = 1, Estado = Estado.Pendiente, Fecha = today.AddDays(-1), Sucursal = new Sucursal { Nombre = "SampleSucName1", Codigo = "SampleSucCod1" }, Comprobante = "REM 0000-00000001" });
            cel.Seguimientos.Add(new Seguimiento { Id = 2, Estado = Estado.EnDeposito, Fecha = today, Sucursal = new Sucursal { Nombre = "SampleSucName2", Codigo = "SampleSucCod2" }, Comprobante = "REM 0000-00000002" });

            this.celulares.Add(cel);

            var controller = this.CreateSeguimientosController();

            var result = controller.Index(123456789123456) as ViewResult;
            Assert.IsNotNull(result);

            var model = result.Model as LastSeguimientoViewModel;
            Assert.IsNotNull(model);
            Assert.AreEqual(123456789123456, model.Imei);
            Assert.AreEqual("En Deposito", model.EstadoActual);
            Assert.AreEqual(today, model.UltimaActividad);
            Assert.IsTrue(model.UltimaUbicacion.Contains("SampleSucName2"));
            Assert.AreEqual("REM 0000-00000002", model.UltimoComprobante);

            this.celularesRepositoryMock.VerifyAll();
            this.principalMock.VerifyAll();
        }

        [TestMethod]
        public void ListShouldReturnSeguimientosForImei()
        {
            this.userRole = Constants.AdministradorRole;
            this.isInRole = true;
            DateTime today = DateTime.Today;
            Celular cel = new Celular { Imei = 123456789123456 };
            cel.Seguimientos.Add(new Seguimiento { Id = 1, Estado = Estado.Pendiente, Fecha = today.AddDays(-1), Sucursal = new Sucursal { Nombre = "SampleSucName1", Codigo = "SampleSucCod1" }, Comprobante = "REM 0000-00000001" });
            Seguimiento segVenta = new Seguimiento { Id = 2, Estado = Estado.EnDeposito, Fecha = today, Sucursal = new Sucursal { Nombre = "SampleSucName2", Codigo = "SampleSucCod2" }, Comprobante = "REM 0000-00000002" };
            cel.Seguimientos.Add(segVenta);
            Venta venta = new Venta { Id = 1, AbonoId = 1, SeguimientoId = 2, Celular = cel, Seguimiento = segVenta };

            this.celulares.Add(cel);
            this.ventas.Add(venta);

            var controller = this.CreateSeguimientosController();

            var result = controller.List(123456789123456, 1, 50) as JsonResult;
            Assert.IsNotNull(result);

            var model = result.Data;
            Assert.IsNotNull(model);

            //// TODO: Deserialize Json and assert for specific content

            this.celularesRepositoryMock.VerifyAll();
            this.principalMock.VerifyAll();
        }

        [TestMethod]
        public void GetAbonoIdShouldReturnEmptyForInvalidSeguimiento()
        {
            this.userRole = Constants.AdministradorRole;
            this.isInRole = true;

            DateTime today = DateTime.Today;
            Celular cel = new Celular { Imei = 123456789123456 };
            Seguimiento segVenta = new Seguimiento { Id = 2, Estado = Estado.Vendido, Fecha = today, Sucursal = new Sucursal { Nombre = "SampleSucName2", Codigo = "SampleSucCod2" }, Comprobante = "REM 0000-00000002" };
            cel.Seguimientos.Add(new Seguimiento { Id = 1, Estado = Estado.Pendiente, Fecha = today.AddDays(-1), Sucursal = new Sucursal { Nombre = "SampleSucName1", Codigo = "SampleSucCod1" }, Comprobante = "REM 0000-00000001" });
            cel.Seguimientos.Add(segVenta);
            this.celulares.Add(cel);

            var controller = this.CreateSeguimientosController();

            var result = controller.GetAbonoId(2) as JsonResult;
            Assert.IsNotNull(result);

            var json = result.Data.ToString();
            Assert.AreEqual("{ abonoId =  }", json);

            this.ventasRepositoryMock.VerifyAll();
            this.principalMock.VerifyAll();
        }

        [TestMethod]
        public void GetAbonoIdShouldReturnAbonoForSeguimiento()
        {
            this.userRole = Constants.AdministradorRole;
            this.isInRole = true;

            DateTime today = DateTime.Today;
            Celular cel = new Celular { Imei = 123456789123456 };
            Seguimiento segVenta = new Seguimiento { Id = 2, Estado = Estado.Vendido, Fecha = today, Sucursal = new Sucursal { Nombre = "SampleSucName2", Codigo = "SampleSucCod2" }, Comprobante = "REM 0000-00000002" };
            Venta venta = new Venta { Id = 1, AbonoId = 1, SeguimientoId = 2, Celular = cel, Seguimiento = segVenta };

            cel.Seguimientos.Add(new Seguimiento { Id = 1, Estado = Estado.Pendiente, Fecha = today.AddDays(-1), Sucursal = new Sucursal { Nombre = "SampleSucName1", Codigo = "SampleSucCod1" }, Comprobante = "REM 0000-00000001" });
            cel.Seguimientos.Add(segVenta);

            this.celulares.Add(cel);
            this.ventas.Add(venta);

            var controller = this.CreateSeguimientosController();

            var result = controller.GetAbonoId(2) as JsonResult;
            Assert.IsNotNull(result);

            var json = result.Data.ToString();
            Assert.AreEqual("{ abonoId = 1 }", json);

            this.ventasRepositoryMock.VerifyAll();
            this.principalMock.VerifyAll();
        }

        private SeguimientosController CreateSeguimientosController(MembershipProvider membershipProvider = null, RoleProvider roleProvider = null)
        {
            var httpContextMock = new Mock<HttpContextBase>();
            httpContextMock.Setup(c => c.User).Returns(() => this.principalMock.Object);
            httpContextMock.Setup(c => c.Request).Returns(new Mock<HttpRequestBase>().Object);
            httpContextMock.Setup(c => c.Response).Returns(new Mock<HttpResponseBase>().Object);

            var httpContext = httpContextMock.Object;

            var routes = new RouteCollection();
            RouteConfig.RegisterRoutes(routes);

            var controller = new SeguimientosController(this.repositoriesMock.Object, membershipProvider, roleProvider)
            {
                ControllerContext = new ControllerContext { HttpContext = httpContext },
                Url = new UrlHelper(new RequestContext(httpContext, new RouteData()), routes),
            };

            return controller;
        }

        private void VerifyAll()
        {
            this.celularesRepositoryMock.VerifyAll();
            this.ventasRepositoryMock.VerifyAll();
            this.repositoriesMock.VerifyAll();
            this.principalMock.VerifyAll();
        }

        private Celular CreateCelular(long imei, Estado lastEstado, string lastSucursalName)
        {
            var today = DateTime.Today;
            var celular = new Celular { Imei = imei };
            celular.Seguimientos.Add(new Seguimiento { Id = 1, Estado = Estado.Pendiente, Fecha = today, Sucursal = new Sucursal { Nombre = "SampleSucName1", Codigo = "SampleSucCod1" } });
            celular.Seguimientos.Add(new Seguimiento { Id = 2, Estado = lastEstado, Fecha = today, Sucursal = new Sucursal { Nombre = lastSucursalName, Codigo = "SampleSucCod2" } });

            return celular;
        }
    }
}
